'''
1、掌握数据集简单预处理的步骤和具体实现。
scikit-learn库是当今最流行的机器学习算法库之一
可用来解决分类与回归问题
本章以鸢尾花数据集为例,简单了解八大传统机器学习分类算法的sk-earn实现
欲深入了解传统机器算法的原理和公式推导,请继续学习《统计学习方法》或《西瓜书》

'''

# 鸢尾花数据集
# 下载数据集
import seaborn as sns

iris = sns.load_dataset("iris")

# 数据集的查看
print(type(iris))
print(iris.head())
iris.info()
iris.describe()
iris.species.value_counts()
sns.pairplot(data=iris, hue="species")

# 标签清洗
print(iris.columns)
iris_simple = iris.drop(["sepal_length", "sepal_width"], axis=1)
iris_simple.head()

# 标签编码
from sklearn.preprocessing import LabelEncoder

encoder = LabelEncoder()
iris_simple["species"] = encoder.fit_transform(iris_simple["species"])
iris_simple.head()

# 数据集的标准化(本数据集特征比较接近,实际处理过程中未标准化)
from sklearn.preprocessing import StandardScaler  # 标准化的工具
import pandas as pd

trans = StandardScaler()
# fit_transfrom 训练获得均值和标准差 然后标准化
_iris_simple = trans.fit_transform(iris_simple[["petal_length", "petal_width"]])
_iris_simple = pd.DataFrame(_iris_simple, columns=["petal_length", "petal_width"])
_iris_simple.describe()

# 构建训练集和测试集(本课暂不考虑验证集)
from sklearn.model_selection import train_test_split

train_set, test_set = train_test_split(iris_simple, test_size=0.2)
# test_set.head()

iris_x_train = train_set[["petal_length", "petal_width"]]
# iris_x_train.head()

iris_y_train = train_set["species"].copy()  # 构建一个新的DataFrame对象
# iris_y_train.head()

iris_x_test = test_set[["petal_length", "petal_width"]]
# iris_x_test.head()

iris_y_test = test_set["species"].copy()
# iris_y_test.head()

'''
2、以鸢尾花数据集为例，
分别调用
K近邻、
朴素贝叶斯、
决策树、
逻辑回归、
支持向量机、
集成方法之随机森林、
Adaboost、
GBDT八大分类算法的sklearn实现对鸢尾花进行分类
'''


#k近邻算法
'''
与待预测点最近的训练数据集中的k个邻居
把k个近邻中最常见的类别预测为带预测点的类别 
'''
# #sklearn实现
# from sklearn. neighbors import KNeighborsClassifier
# #构建分类器对象
# clf =KNeighborsClassifier()
# clf
# #训练
# clf. fit(iris_x_train, iris_y_train)
#
# #预测
# res = clf. predict (iris_x_test)
# print (res)
# print (iris_y_test. values)
#
# #翻转   返回
# encoder. inverse_transform (res)
#
# #评估
# accuracy = clf. score(iris_x_test, iris_y_test)
# print ("预测正确率: {:.0%}". format (accuracy))
#
# #存储数据
# out = iris_x_test. copy ()
# out ["y"] = iris_y_test
# out ["pre"] = res
# out
#
# out. to_csv ("iris_predict. csv")
#
# # 可视化
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
#
#
def draw(clf):
    # 网格化
    M, N = 500, 500
    x1_min, x2_min = iris_simple[["petal_length", "petal_width"]].min(axis=0)
    x1_max, x2_max = iris_simple[["petal_length", "petal_width"]].max(axis=0)
    t1 = np.linspace(x1_min, x1_max, M)
    t2 = np.linspace(x2_min, x2_max, N)
    x1, x2 = np.meshgrid(t1, t2)

    # 预测
    x_show = np.stack((x1.flat, x2.flat), axis=1)
    y_predict = clf.predict(x_show)

    # 配色
    cm_light = mpl.colors.ListedColormap(["#A0FFA0", "#FFA0A0", "#A0A0FF"])
    cm_dark = mpl.colors.ListedColormap(["g", "r", "b"])

    # 绘制预测区域图
    plt.figure(figsize=(10, 6))
    plt.pcolormesh(t1, t2, y_predict.reshape(x1.shape), cmap=cm_light)

    # 绘制原始数据点
    plt.scatter(iris_simple["petal_length"], iris_simple["petal_width"], label=None,
                c=iris_simple["species"], cmap=cm_dark, marker='o', edgecolors='k')
    plt.xlabel("petal_length")
    plt.ylabel("petal_width")

    # 绘制图例
    color = ["g", "r", "b"]
    species = ["setosa", "virginica", "versicolor"]
    for i in range(3):
        plt.scatter([], [], c=color[i], s=40, label=species[i])  # 利用空点绘制图例
    plt.legend(loc="best")
    plt.title('iris_classfier')
    plt.show()
#
# draw(clf)


'''
朴素贝叶斯算法
当x=(x1, x2)发生的时候,哪一个yk发生的概率最大
'''

#sklearn实现
# from sklearn. naive_bayes import GaussianNB
# #构建分类器对象
# clf = GaussianNB ()
#
# #训练
# clf. fit (iris_x_train, iris_y_train)
#
# #预测
# res = clf. predict (iris_x_test)
# print(res)
# print(iris_y_test. values)
#
# #评估
# accuracy = clf. score (iris_x_test, iris_y_test)
# print ("预测正确率: {:.0%} ". format (accuracy))
#
# #可视化
# draw (clf)


'''
决策树算法
CART算法:每次通过一个特征,将数据尽可能的分为纯净的两类,递归的分下去
'''
# #sklearn实现
# from sklearn. tree import DecisionTreeClassifier
# #构建分类器对象
# clf = DecisionTreeClassifier()
# #训练
# clf. fit(iris_x_train, iris_y_train)
#
# #预测
# res = clf. predict (iris_x_test)
# print (res)
# print(iris_y_test. values)
#
# #评估
# accuracy = clf. score (iris_x_test, iris_y_test)
# print ("预测正确率: {:.0%} ". format (accuracy))
#
# #可视化
# draw (clf)


'''
逻辑回归算法
一种解释: 训练:通过一个映射方式,将特征x= (x1, x2)映射成P(y=ck),求使得所有概率之积最大化的映射方式里的参数
预测:计算p(y=ck)取概率最大的那个类别作为预测对象的分类
'''
# #sklearn实现
# from sklearn. linear_model import LogisticRegression
# #构建分类器对象
# clf = LogisticRegression(solver='saga', max_iter=1000)
# clf
#
# #训练
# clf. fit(iris_x_train, iris_y_train)
#
# #预测
# res = clf. predict (iris_x_test)
# print (res)
# print (iris_y_test. values)
#
# #评估
# accuracy = clf. score(iris_x_test, iris_y_test)
# print ("预测正确率: {:.0%}". format (accuracy))
#
# draw(clf)


'''
支持向量机算法
以二分类为例,假设数据可用完全分开:
用一个超平面将两类数据完全分开,且最近点到平面的距离最大
'''
# #sklearn实现
# from sklearn. svm import SVC
# #构建分类器对象
# clf = SVC()
# clf
# #训练
# clf. fit(iris_x_train, iris_y_train)
#
# # 预测
# res = clf. predict (iris_x_test)
# print (res)
# print (iris_y_test. values)
#
# # 评估
# accuracy = clf. score(iris_x_test, iris_y_test)
# print ("预测正确率: {:.0%}". format (accuracy))
#
# #可视化
# draw (clf)

'''
集成方法---随机森林
训练集m,有放回的随机抽取m个数据,构成一组,
共抽取n组采样集n组采样集训练得到n个弱分类器弱分类器
一般用决策树或神经网络将n个弱分类器进行组合得到强分类器
'''

# #sklearn实现
# from sklearn. ensemble import RandomForestClassifier
# #构建分类器对象
# clf = RandomForestClassifier()
# clf
#
# #训练
# clf. fit(iris_x_train, iris_y_train)
#
# #预测
# res = clf. predict(iris_x_test)
# print (res)
# print(iris_y_test. values)
#
# #评估
# accuracy = clf. score(iris_x_test, iris_y_test)
# print ("预测正确率:{:.0%}". format (accuracy))
#
# draw(clf)

'''
集成方法-Adaboost
训练集m,用初始数据权重训练得到第一个弱分类器,根据误差率计算弱分类器系数,更新数据的权重
使用新的权重训练得到第二个弱分类器,以此类推
根据各自系数,将所有弱分类器加权求和获得强分类器 
'''
# #sklean实现
# from sklearn. ensemble import AdaBoostClassifier
# from sklearn. naive_bayes import GaussianNB
#
# #构建分类器对象
# clf = AdaBoostClassifier()
# clf
#
# #训练
# clf. fit(iris_x_train, iris_y_train)
#
# #预测
# res = clf. predict(iris_x_test)
# print (res)
# print(iris_y_test. values)
#
# #评估
# accuracy = clf. score(iris_x_test, iris_y_test)
# print ("预测正确率:{:.0%}". format (accuracy))
#
# draw(clf)


'''
集成方法——梯度提升树GBDTT¶

基本思想

    训练集m,获得第一个弱分类器,获得残差,然后不断地拟合残差
    所有弱分类器相加得到强分类器

'''

# #sklearn实现
# from sklearn. ensemble import GradientBoostingClassifier
# #构建分类器对象
# clf = GradientBoostingClassifier()
# clf
#
# #训练
# clf. fit (iris_x_train, iris_y_train)
#
# #预测
# res = clf. predict(iris_x_test)
# print (res)
# print(iris_y_test. values)
#
# #评估
# accuracy = clf. score(iris_x_test, iris_y_test)
# print ("预测正确率:{:.0%}". format (accuracy))
#
# draw(clf)








# 了解当前流行的分类算法：Xgboost、LightGBM、stacking和神经网络。
'''

大杀器

【1】 xgboost

    GBDT的损失函数只对误差部分做负梯度(一阶泰勒)展开
    XGBoost损失函数对误差部分做二阶泰勒展开,更加准确,更快收敛

【2】 lightgbm

    微软:快速的,分布式的,高性能的基于决策树算法的梯度提升框架 速度更快

【3】 stacking

    堆叠或者叫模型融合
    先建立几个简单的模型进行训练,第二级学习器会基于前级模型的预测结果进行再训练

【4】神经网络

'''